//
//  DataSet.m
//  iMed
//
//  Created by Barry Press on 10/19/09.
//  Copyright 2009 Barry Press. All rights reserved.
//

#import "DataSet.h"
#import "History.h"
#import "MyDocument.h"


@implementation DataSet


#pragma mark New object creation
// =============================================================================
// ---------------------------------------------- createHistoryWithRX ----------
- (History*)createHistoryWithRX:(RX*)anRX atTime:aTime
{
	History *prior, *h = [[[History alloc] initWithRX:anRX 
											 withDose:[anRX dose] 
												Count:[anRX perday]
											   atTime:aTime
								returningPriorHistory:&prior] autorelease];
	// If there is no prior history record with this rx, then the prior 
	// timestamp equals this one, and the interval is zero. Set the 
	// running interval to match.
	if (h != nil) {
		[h setRunninginterval:(prior==nil) ? [h interval] : -1.0];
	}
	return h;
}

// ---------------------------------------------- createNDC --------------------
- (NDCitem*)createNDC
{
	NDCitem* ndc = [[[NDCitem alloc] init] autorelease];
	return ndc;
}

// ---------------------------------------------- createRX ---------------------
- (RX*)createRXForNDC:(NDCitem*)anNDC writtenOnDate:(NSDate*)wDate filledOnDate:(NSDate*)fDate
{
	RX* rx;
	rx = [[[RX alloc] initWithDateWritten:wDate 
							  dateFilled:fDate 
									 Ndc:anNDC
									Dose:(float)1.0
								Interval:(double)4.5*HOUR] autorelease];
	return rx;
}


#pragma mark Calculations
// =============================================================================
// ---------------------------------------------- averageIntervalForRX: --------
- (NSTimeInterval) averageIntervalForRX:(RX*)anRx 
{
	return [self averageIntervalForRX:anRx returnsCount:NULL returnsHistory:NULL];
}

- (NSTimeInterval) averageIntervalForRX:(RX*)anRx returnsCount:(int*)iCount returnsHistory:(History**)anH
{		
	NSAssert(history != nil, @"No history log available.");
	HistoryLog* log = [history sortedHistoryForRX:anRx];

	// The log is a subset of the total history selected for the RX and
	// sorted so the first entry is the oldest. Scan from the back (newest) to
	// find the first history record that's not for today, and use its timestamp,
	// along with the count of the number of records that are today and divide 
	// to get the average. 
	
	int intervalCount = 0;
	History* newerHistory;
	History* hist = [log previousDayRXHistory:anRx 
								   forHistory:NULL 
									inDataSet:self 
								 returnsCount:&intervalCount 
							  andNewerHistory:&newerHistory];
	// hist is the older one, newerHistory is the most recent
	
	NSTimeInterval historyInterval = [[newerHistory timestamp] timeIntervalSinceDate:[hist timestamp]];
	
	NSTimeInterval avg; 
	if (intervalCount <= 0) {
		avg = 0.0;
		intervalCount = 0;
	}
	else {
		avg = historyInterval / intervalCount;
	}
	
	if (iCount != NULL) {
		*iCount = intervalCount;
	}
	if (anH != NULL) {
		*anH = newerHistory;
	}
	return avg;
	
}

// ---------------------------------------------- readyRXArray -----------------
- (NSArray*)getReadyRXArray
{
	NSMutableArray* rxs = [[[NSMutableArray alloc] init] autorelease];
	for (int ix = 0; ix < [forecast count]; ++ix) {
		RXEvent* rxe = [forecast objectAtIndex:ix];
		NSAssert(rxe != nil, @"rxe nil in readyRXArray");
		if ([rxe interval] <= 0.0 && [[rxe rx] bAuto]) {
			[rxs addObject:[rxe rx]];
		}
	}
	return rxs;
}

#pragma mark Archiving and init methods
// =============================================================================
// ---------------------------------------------- dealloc ----------------------
- (void)dealloc
{
	[arrayMeds release];
	arrayMeds = NULL;
	[arrayRXlog release];
	arrayRXlog = NULL;
	[forecast release];
	forecast = NULL;
	[history release];
	history = NULL;
	[super dealloc];
}

// ---------------------------------------------- encodeWithCoder --------------
- (void)encodeWithCoder:(NSCoder *)coder
{
	NSAssert(arrayMeds != NULL, @"NULL arrayMeds pointer in DataSet:encodeWithCoder");
	NSAssert(arrayRXlog != NULL, @"NULL arrayRXlog pointer in DataSet:encodeWithCoder");
	[coder encodeObject:arrayMeds forKey:@"DSarrayMeds"]; 
	[coder encodeObject:arrayRXlog forKey:@"DSarrayRXlog"];
	[coder encodeObject:forecast forKey:@"DSforecast"];
	[coder encodeObject:history forKey:@"DShistory"];
}

// ---------------------------------------------- init -------------------------
- (id)init
{
	[super init];
	arrayMeds = [[[Meds alloc] init] retain];
	arrayRXlog = [[[RXlog alloc] init] retain];
	forecast = [[[ForecastSchedule alloc] init] retain];
	history = [[[HistoryLog alloc] init] retain];
	calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] retain];
	return self;
}

// ---------------------------------------------- initWithCoder ----------------
- (id)initWithCoder:(NSCoder *)coder
{
	[super init];
	calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] retain];
	arrayMeds = [[coder decodeObjectForKey:@"DSarrayMeds"] retain];
	arrayRXlog = [[coder decodeObjectForKey:@"DSarrayRXlog"] retain];
	forecast = [[coder decodeObjectForKey:@"DSforecast"] retain];
	history = [[coder decodeObjectForKey:@"DShistory"] retain];
	return self;
}

#pragma mark Calendar calculations
// =============================================================================
// ---------------------------------------------- isDate:onSameDayAsDate: ------
- (BOOL)isDate:(NSDate*)d1 onSameDayAsDate:(NSDate*)d2
{
	NSDateComponents *d1c = [calendar components:NSWeekdayCalendarUnit
										fromDate:d1];
	[d1c setHour:0];
	[d1c setMinute:0];
	[d1c setSecond:0];
	NSDateComponents *d2c = [calendar components:NSWeekdayCalendarUnit
										fromDate:d2];
	[d2c setHour:0];
	[d2c setMinute:0];
	[d2c setSecond:0];
	return [d1c isEqual:d2c];
}
				 
// =============================================================================
/*
// ---------------------------------------------- printMeds --------------------
- (void)printMeds
{
	[self printarray:(NSArray*)arrayMeds];
}

// ---------------------------------------------- printRXlog -------------------
- (void)printRXlog
{
	[self printarray:(NSArray*)arrayRXlog];
}

// ---------------------------------------------- printarray -------------------
- (void)printarray:(NSArray*)array
{
	NSLog(@" ********** %s array has %d elements **********", NAMEOF(array), [array count]);
	for (int ix = 0; ix < [array count]; ++ix) {
		RX* rx = [array objectAtIndex:ix];
		NSLog(@"%s object at index %d\n%@\n\n", NAMEOF(array), ix, rx);
	}
}
*/

@synthesize arrayMeds;
@synthesize arrayRXlog;
@synthesize forecast;
@synthesize history;

@end
